home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 #1 / Ham Radio 2000.iso / ham2000 / hf / dsp / dsp4tool / spy.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-02-27  |  8.1 KB  |  411 lines

  1. /*  SPY.C -- Show data
  2.  *
  3.  *  Copyright (C) 1991-1994 by Alef Null. All rights reserved.
  4.  *  Author(s): J Vuori
  5.  *  Modification(s):
  6.  */
  7.  
  8.  
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <math.h>
  12. #include <signal.h>
  13. #include <conio.h>
  14. #include <ctype.h>
  15. #include "dsply.h"
  16. #include "fft.h"
  17. #include "serial.h"
  18.  
  19.  
  20. #define N        512     // number of horisontal lines
  21. #define LOGN        9        // log2(N)
  22. #define STEP        8
  23.  
  24. #define PORT        1        // default serial port number
  25. #define BAUD        9600    // baud rate
  26.  
  27. #define EXT           "DAT"   // file's extension
  28.  
  29.  
  30. typedef enum { True = -1, False = 0 } Bool;
  31.  
  32. static struct {
  33.     unsigned ctrlC:1;
  34.     unsigned reso:1;
  35.     unsigned cont:1;
  36.     unsigned fft:1;
  37.     unsigned fix:1;
  38. } flags;
  39.  
  40. typedef struct {
  41.     int  max, min;
  42.     int *cp, data[N];
  43. } SAMPLES;
  44.  
  45.  
  46. /*
  47.  * CTRL-C handler
  48.  */
  49. void cdecl CtrlCHandler(void) {
  50.     flags.ctrlC = 1;
  51.     signal(SIGINT, CtrlCHandler);
  52. }
  53.  
  54.  
  55. static char *AddExtension(char *FileName, char *Extension) {
  56.     static char Name[13];
  57.     char        *s;
  58.     
  59.     s = Name;
  60.     while(*FileName && *FileName != '.')
  61.     *s++ = *FileName++;
  62.         
  63.     if(*FileName)
  64.     while((*s++ = *FileName++) != NULL);
  65.     else {
  66.     *s++ = '.';
  67.     
  68.     while((*s++ = *Extension++) != NULL);
  69.     }
  70.     
  71.     return(Name);
  72. }
  73.  
  74.  
  75. /*
  76.  * Wait (max 3s) for a character from the serial port
  77.  *
  78.  *  returns -1 if there is no character
  79.  */
  80. static int ReadSerialLine(void) {
  81.     unsigned long start;
  82.     int       c;
  83.  
  84.     #define BIOS_TIMER (volatile unsigned long far *)(0x46c)
  85.  
  86.     /* wait until timer changes its state */
  87.     start = *BIOS_TIMER;
  88.     while (start+54L != *BIOS_TIMER)     // 54.9ms*54=3s
  89.     if ((c = ReadSerial()) != -1)
  90.         return (c);
  91.  
  92.     return (-1);
  93. }
  94.  
  95.  
  96. /*
  97.  * Read samples from the DSP CARD 4
  98.  */
  99. static Bool ReadSamples(int *frame) {
  100.     int *p, c;
  101.  
  102.     WriteSerial('S');
  103.  
  104.     if (ReadSerialLine() == 'P') {
  105.     for (p = frame; p < &frame[N]; p++) {
  106.         if ((*p = ReadSerialLine()) == -1)
  107.         return (False);
  108.  
  109.         if ((c = ReadSerialLine()) == -1)
  110.         return (False);
  111.         else
  112.         *p |= (c<<8);
  113.     }
  114.  
  115.     return (True);
  116.     }
  117.  
  118.     return (False);
  119. }
  120.  
  121.  
  122. static Bool nextl(FILE *fd, long *data) {
  123.     int  c;
  124.     char buff[80], *p;
  125.  
  126.     /* first flush leading space out */
  127.     p = buff;
  128.     while (c = getc(fd), !isdigit(c) && c != '-' && c != EOF);
  129.     *p++ = c;
  130.     if (c == EOF) return (False);
  131.  
  132.     /* then get the main body of the character */
  133.     while (c = getc(fd), c != EOF && (isdigit(c) || c == '-'))
  134.     *p++ = c;
  135.  
  136.     *p = '\0';
  137.  
  138.     *data = atol(buff) > 8388608L ? atol(buff)-16777216L : atol(buff);
  139.  
  140.     return (True);
  141. }
  142.  
  143.  
  144. /*
  145.  * Reads one frame from the given file
  146.  */
  147. static Bool readFile(char *name, int *frame) {
  148.     FILE *fp;
  149.     long  d;
  150.     int  *p;
  151.  
  152.     if ((fp = fopen(name, "r")) == NULL)
  153.     return (False);
  154.  
  155.     p = frame;
  156.     while (p < &frame[N])
  157.     if (nextl(fp, &d))
  158.         *p++ = (int)d;
  159.     else {
  160.         fclose(fp);
  161.         return (False);
  162.     }
  163.  
  164.     fclose(fp);
  165.     return (True);
  166. }
  167.  
  168.  
  169. /*
  170.  * Writes one frame to the given file
  171.  */
  172. static Bool writeFile(char *name, int *frame) {
  173.     FILE *fp;
  174.     int  *p;
  175.  
  176.     if ((fp = fopen(name, "w")) == NULL)
  177.     return (False);
  178.  
  179.     p = frame;
  180.     while (p < &frame[N])
  181.     fprintf(fp, "%d\n", *p++);
  182.  
  183.     fclose(fp);
  184.     return (True);
  185. }
  186.  
  187.  
  188. /*
  189.  * Search max and min values
  190.  */
  191. void searchMinMax(SAMPLES *s) {
  192.     int *p;
  193.  
  194.     s->min =  32767;
  195.     s->max = -32767;
  196.  
  197.     for (p = s->data; p < &(s->data[N]); p++) {
  198.     s->min = min(s->min, *p);
  199.     s->max = max(s->max, *p);
  200.     }
  201. }
  202.  
  203.  
  204. /*
  205.  * Calculate spectrum of the given data block
  206.  */
  207. void spectrum(SAMPLES *s) {
  208.     struct complex tmp[N];
  209.     int            i;
  210.  
  211.     /* first transform windowed input samples */
  212.     HanningWin(tmp, s->data, LOGN);
  213.     fft(tmp, LOGN);
  214.  
  215.     /* then calculate the logarithm of the power */
  216.     for (i = 0; i < N; i++)
  217.     s->data[i] = (int)(10.0*log10(
  218.              tmp[Bit_Reverse(i, LOGN)].x*tmp[Bit_Reverse(i, LOGN)].x+
  219.              tmp[Bit_Reverse(i, LOGN)].y*tmp[Bit_Reverse(i, LOGN)].y)+.5);
  220. }
  221.  
  222.  
  223. /*
  224.  * Plot given block
  225.  */
  226. static void plotSamples(SAMPLES *s) {
  227.     int val, i, j = 0;
  228.  
  229.     PlotStart(s->min, s->max);
  230.     for (i = 0; i < N && &(s->cp)[j] < &s->data[N]; i++) {
  231.     if (flags.reso ? !(i % STEP) : 1) {
  232.         val = (s->cp)[j++];
  233.         if (flags.reso) PlotCircle(i, val);
  234.     }
  235.  
  236.     PlotLine(i, val);
  237.     }
  238. }
  239.  
  240.  
  241. int cdecl main(int argc, char *argv[]) {
  242.     static char *logo[] = {
  243.     "Alef Null DSP CARD 4 SPY (" __DATE__ ")",
  244.     "[n]",
  245.     "[A]",
  246.     " ",
  247.     "R, W    read/write file                          ",
  248.     "N, P    go forward/backward                      ",
  249.     "S       read samples from the DSP CARD 4         ",
  250.     "T, C, F toggle coarse/continues/FFT display mode ",
  251.     ".       exit from the program                    ",
  252.     NULL
  253.     };
  254.     SAMPLES samples;
  255.     int     port = PORT;
  256.     char   *filename = "LOG", option;
  257.  
  258.     /* first parse arguments */
  259.     argc--; argv++;
  260.     while(argc > 0) {
  261.     switch(**argv) {
  262.     case '-':
  263.         switch(option = *(++(*argv))) {
  264.         /* port selection */
  265.         case 'p':
  266.         case 'P':
  267.         port = atoi(++(*argv));
  268.         break;
  269.  
  270.         default:
  271.         fprintf(stderr, "unknown option '%c', type 'spy ?' to get the allowed options\n", option);
  272.         break;
  273.         }
  274.         break;
  275.  
  276.     case '?':
  277.         fprintf(stderr, "usage: spy [-p<portno>]\n");
  278.         fprintf(stderr, "\t-p<portno> uses the specified (1 (default) or 2) serial port\n");
  279.         return (0);
  280.  
  281.     default:
  282.         filename = *argv;
  283.         break;
  284.     }
  285.  
  286.     argc--; argv++;
  287.     }
  288.  
  289.     /* then open serial line */
  290.     signal(SIGINT, CtrlCHandler);
  291.     if (!OpenSerial(port, BAUD)) {
  292.     fprintf(stderr, "can't open serial port COM%d\n", port);
  293.     return (1);
  294.     }
  295.  
  296.     /* open graphic display */
  297.     if (InitDisplay(N, logo)) {
  298.     fprintf(stderr, "%s: no support for the needed graphics device (VGA)\n", __FILE__);
  299.     CloseSerial();
  300.     return (1);
  301.     }
  302.  
  303.     /* try to show default file at the first */
  304.     samples.cp = samples.data;
  305.     if (readFile(AddExtension(filename, EXT), samples.data) == True) {
  306.     searchMinMax(&samples);
  307.     plotSamples(&samples);
  308.     }
  309.  
  310.     /* finally obey user instructions */
  311.     while (True) {
  312.     /* terminate if user is in panic */
  313.     if (flags.ctrlC)
  314.         goto end;
  315.  
  316.     /* if key pressed, obey the given command */
  317.     if (kbhit())
  318.         switch (toupper(getch())) {
  319.         case 'R':
  320.         if (readFile(AddExtension(filename, EXT), samples.data) == True) {
  321.             if (flags.fft)
  322.             spectrum(&samples);
  323.  
  324.             searchMinMax(&samples);
  325.             plotSamples(&samples);
  326.         } else
  327.             putchar('\x7');
  328.         break;
  329.  
  330.         case 'W':
  331.         if (writeFile(AddExtension(filename, EXT), samples.data) == False)
  332.             putchar('\x7');
  333.         break;
  334.  
  335.         case 'S':
  336.         if (ReadSamples(samples.data) == True) {
  337.             if (flags.fft)
  338.             spectrum(&samples);
  339.  
  340.             if (!flags.fix)
  341.             searchMinMax(&samples);
  342.             plotSamples(&samples);
  343.         } else
  344.             putchar('\x7');
  345.         break;
  346.  
  347.         case 'N':
  348.         samples.cp = min(&samples.data[N-(flags.reso ? STEP : N)-1], samples.cp+(flags.reso ? STEP : N));
  349.         plotSamples(&samples);
  350.         break;
  351.  
  352.         case 'P':
  353.         samples.cp = max(samples.data, samples.cp-(flags.reso ? STEP : N));
  354.         plotSamples(&samples);
  355.         break;
  356.  
  357.         case 'T':
  358.         flags.reso = !flags.reso;
  359.         plotSamples(&samples);
  360.         break;
  361.  
  362.         case 'C':
  363.         flags.cont = !flags.cont;
  364.         break;
  365.  
  366.         case 'X':
  367.         flags.fix = !flags.fix;
  368.         samples.min = -32000;
  369.         samples.max =  32000;
  370.         break;
  371.  
  372.         case 'F':
  373.         flags.fft = !flags.fft;
  374.         if (flags.fft) {
  375.             spectrum(&samples);
  376.             searchMinMax(&samples);
  377.             plotSamples(&samples);
  378.         }
  379.         break;
  380.  
  381.         case '.':
  382.         goto end;
  383.         break;
  384.  
  385.         default:
  386.         putchar('\x7');
  387.         break;
  388.         }
  389.  
  390.     /* continuously sample if in continuous mode */
  391.     if (flags.cont)
  392.         if (ReadSamples(samples.data) == True) {
  393.         if (flags.fft)
  394.             spectrum(&samples);
  395.  
  396.         if (!flags.fix)
  397.             searchMinMax(&samples);
  398.  
  399.         plotSamples(&samples);
  400.         } else {
  401.         putchar('\x7');
  402.         flags.cont = 0;
  403.         }
  404.     }
  405.  
  406. end:
  407.     ReleaseDisplay();
  408.     CloseSerial();
  409.     return (0);
  410. }
  411.